Multiple tapdisk2 processes may use the same parent disk images (later used to
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 17 Dec 2009 06:27:57 +0000 (06:27 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 17 Dec 2009 06:27:57 +0000 (06:27 +0000)
detect sharable memory pages). This patch establishes unique id for each disk
image opened by tapdisk2, and stores it in shared memory region, thus making it
available to the remaining tapdisk2s.

Signed-off-by: Grzegorz Milos <Grzegorz.Milos@citrix.com>
tools/blktap2/drivers/tapdisk-image.c
tools/blktap2/drivers/tapdisk-image.h
tools/memshr/interface.c
tools/memshr/memshr.h
tools/memshr/shm.c
tools/memshr/shm.h

index 6da7f48bd8cdd5095f7c5d23c40aed7c5a9d9afd..400c467583cc60e5715f0dabbe75f5bfdb060d73 100644 (file)
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <memshr.h>
 
 #include "tapdisk-image.h"
 #include "tapdisk-driver.h"
@@ -52,10 +53,11 @@ tapdisk_image_allocate(char *file, int type, int storage,
                return NULL;
        }
 
-       image->type    = type;
-       image->flags   = flags;
-       image->storage = storage;
-       image->private = private;
+       image->type      = type;
+       image->flags     = flags;
+       image->storage   = storage;
+       image->private   = private;
+    image->memshr_id = memshr_vbd_image_get(file);
        INIT_LIST_HEAD(&image->next);
 
        return image;
@@ -69,6 +71,7 @@ tapdisk_image_free(td_image_t *image)
 
        list_del(&image->next);
 
+    memshr_vbd_image_put(image->memshr_id);
        free(image->name);
        tapdisk_driver_free(image->driver);
        free(image);
index 8779dff8b766fa43e6b9e1c046111b7dc8a75c83..33b1b851c358e1f9918a56701a9ce67fbef97107 100644 (file)
@@ -34,6 +34,7 @@
 struct td_image_handle {
        int                          type;
        char                        *name;
+    uint16_t                     memshr_id;
 
        td_flag_t                    flags;
        int                          storage;
index 2c2f45423b9e94c3235e607b8119db0e88c16c7e..ad14bbf2a0a69ccd1ab55e5df19ea0ae3f3350c7 100644 (file)
@@ -106,3 +106,23 @@ void memshr_vbd_initialize(void)
     vbd_info.enabled = 1;
 }
 
+uint16_t memshr_vbd_image_get(char* file)
+{
+    uint16_t id;
+
+    if(pthread_mutex_lock(&SHARED_INFO->lock)) goto error_out;
+    id = shm_vbd_image_get(file, SHARED_INFO->vbd_images);
+    if(pthread_mutex_unlock(&SHARED_INFO->lock)) goto error_out;
+
+    return id;
+error_out:
+    return 0;    
+}
+
+void memshr_vbd_image_put(uint16_t memshr_id)
+{
+    if(pthread_mutex_lock(&SHARED_INFO->lock)) return;
+    shm_vbd_image_put(memshr_id, SHARED_INFO->vbd_images);
+    if(pthread_mutex_unlock(&SHARED_INFO->lock)) return;
+}
+
index 351323715c182b479a60b3ca073258b0fe057dc1..1292d494f5458720cbed5a0ee13bc61aa75fe957 100644 (file)
@@ -26,5 +26,7 @@ typedef uint64_t xen_mfn_t;
 extern void memshr_set_domid(int domid);
 extern void memshr_daemon_initialize(void);
 extern void memshr_vbd_initialize(void);
+extern uint16_t memshr_vbd_image_get(char* file);
+extern void memshr_vbd_image_put(uint16_t memshr_id);
 
 #endif /* __MEMSHR_H__ */
index 6489f614665675eedc255cd08080f2f7c6ab2256..dcbea1e223516f662aa02daaa9a329d339c66f33 100644 (file)
@@ -92,10 +92,11 @@ shared_memshr_info_t * shm_shared_info_open(int unlink)
 {
     shared_memshr_info_t *shared_info;
     pthread_mutexattr_t  lock_attr;
+    int nr_pages, i;
 
-    assert(sizeof(shared_memshr_info_t) < XC_PAGE_SIZE);
+    nr_pages = (sizeof(shared_memshr_info_t) >> XC_PAGE_SHIFT) + 1;
     if(shm_area_open(MEMSHR_INFO_SHM_FILE, 
-                     XC_PAGE_SIZE,
+                     nr_pages * XC_PAGE_SIZE,
                      unlink, 
                      &(shm_info.shared_info_area)) < 0)
     {
@@ -115,6 +116,12 @@ shared_memshr_info_t * shm_shared_info_open(int unlink)
             DPRINTF("Failed to init shared info lock.\n");
             return NULL;
         }
+        strcpy(shared_info->vbd_images[0].file, "list-head");
+        for(i=1; i<MAX_NR_VBD_IMAGES; i++)
+        {
+            shared_info->vbd_images[i].next = i; 
+            shared_info->vbd_images[i].prev = i; 
+        }
         shared_info->magic = MEMSHR_INFO_MAGIC;
     } 
     else
@@ -180,3 +187,77 @@ struct blockshr_hash * shm_blockshr_hash_open(int unlink)
     return h;
 } 
 
+uint16_t shm_vbd_image_get(char* file, vbd_image_info_t *vbd_imgs)
+{
+    vbd_image_info_t *img, *next_img;
+    int i, img_id;
+
+    /* Try to find the file in the existing list first */ 
+    img = vbd_imgs;
+    while(img->next != 0)
+    {
+        img = vbd_imgs + img->next;
+        if(strncmp(img->file, file, MAX_NAME_LEN) == 0)
+        {
+            img->ref_cnt++;
+            return (uint16_t)(img - vbd_imgs); 
+        }
+    }
+    
+    /* Couldn't find an existing entry. We need to add one. Find empty slot */ 
+    for(i=1; i<MAX_NR_VBD_IMAGES; i++)
+    {
+        img = vbd_imgs + i;
+        if((img->next == i) && (img->prev == i))
+            break;
+    }
+    /* No entries left! */
+    if(i == MAX_NR_VBD_IMAGES)
+    {
+        DPRINTF("No space in vbds table.\n");
+        return 0;
+    }
+    if(strlen(file) > MAX_NAME_LEN)
+    {
+        DPRINTF("Filename: %s too long (>%d).\n", file, MAX_NAME_LEN);
+        return 0; 
+    }
+    /* Init the entry */
+    img_id = (img - vbd_imgs);
+    next_img = vbd_imgs + vbd_imgs[0].next;
+    strcpy(img->file, file);
+    img->ref_cnt = 1;
+    img->next = vbd_imgs[0].next;
+    img->prev = 0;
+    next_img->prev = img_id;
+    vbd_imgs[0].next = img_id;
+
+    return img_id;
+}
+
+
+void shm_vbd_image_put(uint16_t memshr_id, vbd_image_info_t *vbd_imgs)
+{
+    vbd_image_info_t *img, *next_img, *prev_img;
+    
+    img = vbd_imgs + memshr_id;
+    if(img->ref_cnt == 0)
+    {
+        DPRINTF("Incorrect image put.\n");
+        return;
+    }
+
+    img->ref_cnt--; 
+
+    /* Remove from list if ref_cnt is zero */
+    if(img->ref_cnt == 0)
+    {
+        next_img = vbd_imgs + img->next;
+        prev_img = vbd_imgs + img->prev;
+        prev_img->next = img->next;
+        next_img->prev = img->prev;
+        img->next = img->prev = (img - vbd_imgs);
+        memset(img->file, 0, MAX_NAME_LEN);
+    }
+}
+
index 0f6f665c6da50dd143b37669792c06347e45085b..0d849ff787464ef3d80e9eb85d794abead214c24 100644 (file)
 #define __SHM_H__
 
 #include <pthread.h>
+#include <unistd.h>
 
+#define MAX_NAME_LEN  1000
+
+typedef struct vbd_image_info {
+    char     file[MAX_NAME_LEN];
+    int      ref_cnt;
+    uint16_t next;
+    uint16_t prev;
+} vbd_image_info_t;
+
+#define MAX_NR_VBD_IMAGES   4096
 typedef struct shared_memshr_info {
-    unsigned long   magic;
-    pthread_mutex_t lock;
-    int             fgprtshr_hash_inited;
-    int             blockshr_hash_inited;
+    unsigned long    magic;
+    pthread_mutex_t  lock;
+    int              fgprtshr_hash_inited;
+    int              blockshr_hash_inited;
+    vbd_image_info_t vbd_images[MAX_NR_VBD_IMAGES];
 } shared_memshr_info_t;
 
 shared_memshr_info_t * shm_shared_info_open(int unlink);
 struct fgprtshr_hash * shm_fgprtshr_hash_open(int unlink);
 struct blockshr_hash * shm_blockshr_hash_open(int unlink);
+uint16_t shm_vbd_image_get(char* file, vbd_image_info_t *vbd_imgs);
+void     shm_vbd_image_put(uint16_t memshr_id, vbd_image_info_t *vbd_imgs);
 
 #endif /* __SHM_H__ */